#ifndef _MULTIBUTTON_H_
#define _MULTIBUTTON_H_

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include <string.h>
#include <stdio.h>
#include "usart/bsp_usart.h"

#define TICKS_INTERVAL            5       // ms
#define DEBOUNCE_TICKS            3       // 消抖轮询次数
#define SHORT_TICKS               (300 / TICKS_INTERVAL)
#define LONG_TICKS                (1000 / TICKS_INTERVAL)

typedef void (*BtnCallback)(void*);   // BtnCallback指向一个参数为void*, 返回值为空的函数

/* 按键事件 */
typedef enum
{
  PRESS_DOWN = 0,         // 按键按下
  PRESS_UP,               // 按键弹起
  PRESS_REPEAT,           // 重复按下触发 
  SINGLE_CLICK,           // 单击按键
  DOUBLE_CLICK,           // 双击按键
  LONG_PRESS_START,       // 达到长按阈值后触发
  LONG_PRESS_HOLD,        // 长按后一直触发
  NUM_OF_EVENTS,
  PRESS_NONE,
} PressEvent;

/* 定义一个按键对象,包含链表 */
typedef struct _Button
{
  uint16_t  ticks;                        // 轮询计时用
  uint8_t   repeat : 4;                   // 重复按下计数，使用位域表示法
  uint8_t   event : 4;                    // 存储按键事件
  uint8_t   state : 3;                    // 按键状态
  uint8_t   debounce_cnt : 3;             // 消抖计数
  uint8_t   active_level : 1;             // 触发有效电平
  uint8_t   button_level : 1;             // 按键实时的一个状态(电平)   
  uint8_t (*hal_button_level)(void);      // 回调函数，传入按键状态函数  
  BtnCallback cb[NUM_OF_EVENTS];          // 回调函数数组，传入事件状态函数
  struct _Button* next;                   // 构成链表
} Button;

/* 菜单的页面 */
typedef enum
{
  MAIN_PAGE = 0,
  LOG_PAGE,
} MENU;

/* 事件值 */
typedef enum
{
  NULL_KEY_EVENT = -1,
  LEFT_KEY_SHORT = 0,
  LEFT_KEY_LONG,
  ENTER_KEY_SHORT,
  ENTER_KEY_LONG,
  RIGHT_KEY_SHORT,
  RIGHT_KEY_LONG,
  UP_KEY_SHORT,
  UP_KEY_LONG,
  DOWN_KEY_SHORT,
  DOWN_KEY_LONG,
  ESC_KEY_SHORT,
  ESC_KEY_LONG,
  POWER_KEY_SHORT,
  POWER_KEY_LONG,
} MENY_KEY_EVENT;

/* 菜单操作结构体 */
typedef struct _Menu
{
  /* 当前正在执行的界面 */
  uint8_t currentPage;
  /* 当前触发的事件 */
  int keyEvent;
} STR_MENU;

/******************** 菜单相关的函数 **********************************/
void menu_init(STR_MENU* handle, uint8_t page, int event_code);

void Set_Menu(STR_MENU* handle, uint8_t page);

uint8_t Get_Menu(STR_MENU* handle);

void Set_Event_Code(STR_MENU* handle, int event_code);

int Get_Event_Code(STR_MENU* handle);

void Menu_Handler(STR_MENU* handle);

/******************** 按键相关的函数 **********************************/
void button_init(Button* handle, uint8_t (*pin_level)(), uint8_t active_level);

void button_attach(Button* handle, PressEvent event, BtnCallback cb);

PressEvent get_button_event(Button* handle);

void button_handler(Button* handle);

int button_start(Button* handle);

void button_stop(Button* handle);

void button_tick(void);
#endif
